<?php
/*
 * Yii Extension of introJS v0.3.0
 * https://code.google.com/p/introjs-yii-extension
 * @license MIT licensed
 * @author Alexander Tonkin
 * @copyright Copyright (c) 2013, Alexander Tonkin
 */
class IntroJs extends CWidget {
	private $_assetsUrl;

	/**
	 * @var array Default options.
	 */
	private $_defaultOptions = array(
		'nextLabel' => 'Next &rarr;',
		'prevLabel' => '&larr; Back',
		'skipLabel' => 'Skip',
		'tooltipPosition' => 'bottom',
	);

	protected $packageId = 'IntroJsYiiPackage';

	/**
	 * @var string Extension id.
	 */
	public $id = 'introJsYii';

	/**
	 * @var boolean Auto start intro.
	 */
	public $autoStart = false;

	/**
	 * @var string JavaScript object of DOM element or
	 * a selector of the element that will be overlayed with the layer.
	 * When is null the default is document.body.
	 * When a JavaScript object is used, the value is for example 'document.body'.
	 * When a selector is used, the value must contain quotes for example "'body'".
	 */
	public $targetElm = null;
	
	/**
	 * @var array Options.
	 */
	public $options = array();

	/**
	 * @var boolean Is 'data-intro' value not safe and use CHtml::encode or
	 * is safe and not use CHtml::encode and allow html formatting.
	 */
	public $isDataSafe = false;

	/**
	 * @var array Data array.
	 * The data array has the following structure:
	 * array(
	 * 	array(
	 * 		'id' => 'id of HTML element',
	 * 		'info' => array(
	 * 			'data-step' => <intro number - int>,
	 * 			'data-intro' => 'intro text',
	 * 			'data-position' => 'top|right|left|bottom',
	 * 		)
	 * 	),
	 * 	// Optional
	 * 	array(
	 * 		'id' => 'id of HTML element to assign onclick event to start intro',
	 * 		'start' => true,
	 * 	),
	 * ),
	 */
	public $data = array();

	public function run() {
		Yii::app()->clientScript
		->addPackage($this->packageId, $this->getPackage())
		->registerPackage($this->packageId)
		->registerScript($this->id, sprintf('var %s = introJs(%s).setOptions(%s);', $this->id, $this->targetElm, $this->getJsOptions()), CClientScript::POS_END);

		$this->registerIntroData();

		if($this->autoStart) {
			Yii::app()->clientScript
			->registerScript($this->id . 'AutoStart', sprintf('%s.start();', $this->id));
		}
	}

	/**
	 * Returns the URL to the published assets folder.
	 * @return string the URL
	 */
	protected function getAssetsUrl() {
		if ($this->_assetsUrl !== null) {
			return $this->_assetsUrl;
		}
		else {
			$assetsPath = Yii::getPathOfAlias('application.extensions.introjs.assets');

			if (YII_DEBUG)
				$assetsUrl = Yii::app()->assetManager->publish($assetsPath, false, -1, true);
			else
				$assetsUrl = Yii::app()->assetManager->publish($assetsPath);

			return $this->_assetsUrl = $assetsUrl;
		}
	}

	/**
	 * Returns the package to add.
	 * @return array the package
	 */
	protected function getPackage() {
		return array(
			'baseUrl' => $this->getAssetsUrl(),
			'js' => array(
				YII_DEBUG ? 'js/intro.js' : 'js/intro.min.js',
			),
			'css' => array(
				YII_DEBUG ? 'css/introjs.css' : 'css/introjs.min.css',
				YII_DEBUG ? 'css/introjs-ie.css' : 'css/introjs-ie.min.css',
			),
			'depends' => array(
				'jquery',
			),
		);
	}

	/**
	 * Returns merged default otions and options and encodes in JS.
	 */
	protected function getJsOptions() {
		$options = $this->_defaultOptions;
		foreach($options as $k => &$v) {
			if($this->options[$k] != '') {
				$v = CHtml::encode($this->options[$k]);
			}
		}
		return CJavaScript::encode($options);
	}

	protected function registerIntroData() {
		if(!is_array($this->data)) {
			throw new CException('IntroJs::data is not an array.');
		}
		foreach($this->data as $data) {
			if(is_array($data['info']) && !$this->isDataSafe) {
				foreach($data['info'] as &$v) {
					$v = CHtml::encode($v);
				}
			}
			$scriptId = $this->id . $data['id'];
			if(isset($data['start']) && $data['start'] === true) {
				$scriptId .= 'Start';
				$script = sprintf('jQuery("#%s").attr("onclick","javascript:%s.start();");', $data['id'], $this->id);
			}
			else {
				$script = sprintf('jQuery("#%s").attr(%s);', $data['id'], CJavaScript::encode($data['info']));
			}
			Yii::app()->clientScript->registerScript($scriptId, $script);
		}
	}
}
?>